﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using Microsoft.Exchange.WebServices.Autodiscover;
using Microsoft.Exchange.WebServices.Data;
using Microsoft.Exchange.WebServices.Dns;
using Entity;
using Utility;
using Newtonsoft.Json;

namespace EWService
{
    public class EWService
    {
        public static ExchangeService Connection(UserAccount _ua)
        {
            string[] _temp = _ua.MailAddress.Split('@');

            ExchangeService _service = null;
            _service = new ExchangeService();
            //switch (_ua.ServiceType)
            //{
            //    case ServiceType.EWS_2007_SP1:
            //        _service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
            //        break;
            //    case ServiceType.EWS_2010:
            //        _service = new ExchangeService(ExchangeVersion.Exchange2010);
            //        break;
            //    case ServiceType.EWS_2010_SP1:
            //        _service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
            //        break;
            //    default: break;
            //}

            if (_ua.EWSDomain != null)
            {
                _service.Credentials = new NetworkCredential(_temp[0], _ua.MailPassword, _ua.EWSDomain);
            }
            else
            {
                _service.Credentials = new NetworkCredential(_temp[0], _ua.MailPassword);
            }

            _service.AutodiscoverUrl(_ua.MailAddress);
            //string ssss = _service.RequestedServerVersion.ToString();

            return _service;
        }

        public static void CreateFolder(UserAccount _ua, string _folderName, string _parentFolderID)
        {
            Folder _folder = new Folder(ConnectionCache.Connections["EWS_" + _ua.MailAddress] as ExchangeService);
            _folder.DisplayName = _folderName;
            _folder.Save((FolderId)_parentFolderID);
        }

        public static void DeleteFolder(UserAccount _ua, string _targetFolderID, DeleteModes _mode)
        {
            Folder _folder = Folder.Bind(ConnectionCache.Connections["EWS_" + _ua.MailAddress] as ExchangeService, _targetFolderID);

            switch (_mode)
            {
                case DeleteModes.HardDelete:
                    _folder.Delete(DeleteMode.HardDelete);
                    break;
                case DeleteModes.SoftDelete:
                    _folder.Delete(DeleteMode.SoftDelete);
                    break;
                case DeleteModes.MoveToDeletedItems:
                    _folder.Delete(DeleteMode.MoveToDeletedItems);
                    break;
                default:break;
            }
            //SearchFolder
            //Folder _folder = new Folder(_service);
            //_folder.Id = _folderName;
            //_folder.Delete(DeleteMode.HardDelete);
            
        }

        public static void RenameFolder(UserAccount _ua, string _targetFolderID, string _newName)
        {
            Folder _folder = Folder.Bind(ConnectionCache.Connections["EWS_"+_ua.MailAddress] as ExchangeService, _targetFolderID);
            _folder.DisplayName = _newName;
            _folder.Update();
        }

        public static List<MailFolder> GetFolderList(UserAccount _ua, MailFolderType _folderType)
        {
            Folder _tempFolder = null;
            FindFoldersResults _findResults = null;
            List<MailFolder> _list = new List<MailFolder>();
            MailFolder _folder;
            ExchangeService _service = ConnectionCache.Connections["EWS_" + _ua.MailAddress] as ExchangeService;

            if (_folderType == MailFolderType.MsgRoot)
            {
                _tempFolder = Folder.Bind(_service, WellKnownFolderName.MsgFolderRoot);
                _findResults = _service.FindFolders(WellKnownFolderName.MsgFolderRoot, new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep });
            }
            else if (_folderType == MailFolderType.Inbox)
            {
                _tempFolder = Folder.Bind(_service, WellKnownFolderName.Inbox);
                _findResults = _service.FindFolders(WellKnownFolderName.Inbox, new FolderView(int.MaxValue) { Traversal = FolderTraversal.Deep });
            }

            _folder = new MailFolder();
            _folder.FolderID = _tempFolder.Id.ToString();
            _folder.DisplayName = _tempFolder.DisplayName.ToString();
            _folder.ChildFolderCount = _tempFolder.ChildFolderCount;
            _list.Add(_folder);

            foreach (Folder _item in _findResults.Folders)
            {
                _folder = new MailFolder();
                _folder.FolderID = _item.Id.ToString();
                _folder.DisplayName = _item.DisplayName.ToString();
                _folder.ChildFolderCount = _item.ChildFolderCount;
                _folder.ParentFolderID = _item.ParentFolderId.ToString();

                _list.Add(_folder);
            }

            return _list;
        }

        public static MailList GetMailList(UserAccount _ua, string _folderID, int _pageCount, int _offset, bool _isInit)
        {
            MailList _list = new MailList();
            Mail _mail;

            ExchangeService _service = ConnectionCache.Connections["EWS_" + _ua.MailAddress] as ExchangeService;
            SearchFilter sf = new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false);
            ItemView iv = new ItemView(_pageCount, _offset);
            //FindItemsResults<Item> findResults2 = es.FindItems(WellKnownFolderName.Inbox, sf, iv);
            //FindItemsResults<Item> findResults = _service.FindItems(_folderID, iv)
            FindItemsResults<Item> findResults = null;
            if (_isInit)
            {
                findResults = _service.FindItems(_folderID, iv);
            }
            else
            {
                findResults = _service.FindItems(_folderID, sf, iv);
            }

            foreach (Item _item in findResults.Items)
            {
                if (_item is EmailMessage)
                {
                    _mail = new Mail();
                    EmailMessage _em = _item as EmailMessage;
                    _em.IsRead = true;
                    _em.Update(ConflictResolutionMode.AutoResolve);
                    //ContactList _cl;
                    _em.Subject.ToString();
                    //_em.Load();

                    _mail.MailUID = _em.Id.ToString();/////////////////////////////UID
                    _mail.Subject = _em.Subject;///////////////////////////////////Subject
                    _mail.FromAddress = _em.From.Address;//////////////////////////From Address
                    _mail.FromName = _em.From.Name;////////////////////////////////From Display Name

                    ContactNameCard _cnc;
                    _mail.To = new List<ContactNameCard>();/////////////////////////To

                    for (int i = 0; i < _em.ToRecipients.Count; i++)
                    {
                        _cnc = new ContactNameCard();
                        _cnc.ContactName = _em.ToRecipients[i].Name;
                        _cnc.MailAddress = _em.ToRecipients[i].Address;

                        _mail.To.Add(_cnc);
                    }

                    _mail.Cc = new List<ContactNameCard>();///////////////////////Cc

                    for (int i = 0; i < _em.CcRecipients.Count; i++)
                    {
                        _cnc = new ContactNameCard();
                        _cnc.ContactName = _em.CcRecipients[i].Name;
                        _cnc.MailAddress = _em.CcRecipients[i].Address;

                        _mail.Cc.Add(_cnc);
                    }

                    _mail.Bcc = new List<ContactNameCard>();////////////////////Bcc

                    for (int i = 0; i < _em.BccRecipients.Count; i++)
                    {
                        _cnc = new ContactNameCard();
                        _cnc.ContactName = _em.BccRecipients[i].Name;
                        _cnc.MailAddress = _em.BccRecipients[i].Address;

                        _mail.Cc.Add(_cnc);
                    }

                    //switch (_em.Body.BodyType)//////////////////////////////////MailBody
                    //{
                    //    case BodyType.HTML:
                    //        _mail.HTMLContent = _em.Body.Text;
                    //        break;
                    //    case BodyType.Text:
                    //        _mail.TextContent = _em.Body.Text;
                    //        break;
                    //    default: break;
                    //}

                    if (_em.HasAttachments)
                    {
                        AttachmentFiles _attFile;
                        _mail.AttachmentFileList = new List<AttachmentFiles>();

                        for (int i = 0; i < _em.Attachments.Count; i++)
                        {
                            _attFile = new AttachmentFiles();

                            FileAttachment _fa = _em.Attachments[i] as FileAttachment;
                            _fa.Load();

                            _attFile.ID = _fa.Id;
                            _attFile.FileName = _fa.FileName;
                            if (_fa.FileName == null)
                                _attFile.FileName = _fa.Name;

                            _attFile.Name = _fa.Name;
                            //_attFile.FileName = _fa.FileName.ToString();
                            _attFile.FileCodes = Convert.ToBase64String(_fa.Content);
                            _attFile.TransferEncoding = "base64";
                            //_attFile.FileCodes=_em.Attachments[i]
                            //_attList.Add(_attFile);
                            _mail.AttachmentFileList.Add(_attFile);
                        }
                        //_mail.AttachmentFileList = _attList;
                        //_mail.AttachmentFileList = JsonConvert.SerializeObject(_attList);
                    }

                    _list.MailItems.Add(_mail);
                }
            }

            _list.MoreAvailable = findResults.MoreAvailable;
            if (findResults.NextPageOffset != null)
                _list.NextPageOffset = (int)findResults.NextPageOffset;
            _list.TotalCount = findResults.TotalCount;

            return _list;
        }

        public static int GetMailCounts(UserAccount _ua, int _pageCount, int _offset, bool _isInit)
        {
            List<MailFolder> _list = GetFolderList(_ua, MailFolderType.Inbox);
            ExchangeService _service = ConnectionCache.Connections["EWS_" + _ua.MailAddress] as ExchangeService;
            SearchFilter _sf = new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false);
            ItemView _iv = new ItemView(_pageCount, _offset);
            FindItemsResults<Item> _findResults = null;
            int _count = 0;

            if (_isInit)
            {
                foreach (MailFolder _item in _list)
                {
                    _findResults = _service.FindItems(_item.FolderID, _iv);
                    _count = _count + _findResults.TotalCount;
                }
            }
            else
            {
                foreach (MailFolder _item in _list)
                {
                    _findResults = _service.FindItems(_item.FolderID, _sf, _iv);
                    _count = _count + _findResults.TotalCount;
                }
            }

            return _count;
        }

        public static void DeleteMail(UserAccount _ua, string _targetMailID, DeleteModes _mode)
        {
            EmailMessage em = EmailMessage.Bind(ConnectionCache.Connections["EWS_" + _ua.MailAddress] as ExchangeService, _targetMailID);
            
            switch (_mode)
            {
                case DeleteModes.HardDelete:
                    em.Delete(DeleteMode.HardDelete);
                    break;
                case DeleteModes.MoveToDeletedItems:
                    em.Delete(DeleteMode.MoveToDeletedItems);
                    break;
                case DeleteModes.SoftDelete:
                    em.Delete(DeleteMode.SoftDelete);
                    break;
                default: break;
            }
        }

        public static void MoveMail(UserAccount _ua, string _mailID, string _targetFolderID)
        {
            EmailMessage em = EmailMessage.Bind(ConnectionCache.Connections["EWS_" + _ua.MailAddress] as ExchangeService, _mailID);

            em.Move(_targetFolderID);
        }

        public static void CopyMail(UserAccount _ua, string _mailID, string _targetFolderID)
        {
            EmailMessage em = EmailMessage.Bind(ConnectionCache.Connections["EWS_" + _ua.MailAddress] as ExchangeService, _mailID);
            
            em.Copy(_targetFolderID);
        }

        public static EmailMessage CreateMail(UserAccount _ua, Mail _mail)
        {
            EmailMessage _em = new EmailMessage(ConnectionCache.Connections["EWS_" + _ua.MailAddress] as ExchangeService);
            EmailAddress _ea = null;
            if (_mail.To != null)
            {
                for (int i = 0; i < _mail.To.Count; i++)
                {
                    if (_mail.To[i].ItemID == null)
                    {
                        _em.ToRecipients.Add(_mail.To[i].MailAddress.ToString());
                    }
                    else
                    {
                        _ea.Id = _mail.To[i].ItemID;
                        _ea.Name = _mail.To[i].ContactName;
                        _ea.Address = _mail.To[i].MailAddress;

                        _em.ToRecipients.Add(_ea);
                    }
                }
            }
            if (_mail.Cc != null)
            {
                for (int i = 0; i < _mail.Cc.Count; i++)
                {
                    if (_mail.Cc[i].ItemID == null)
                    {
                        _em.CcRecipients.Add(_mail.Cc[i].MailAddress.ToString());
                    }
                    else
                    {
                        _ea.Id = _mail.Cc[i].ItemID;
                        _ea.Name = _mail.Cc[i].ContactName;
                        _ea.Address = _mail.Cc[i].MailAddress;

                        _em.CcRecipients.Add(_ea);
                    }
                }
            }
            if (_mail.Bcc != null)
            {
                for (int i = 0; i < _mail.Bcc.Count; i++)
                {
                    if (_mail.Bcc[i].ItemID == null)
                    {
                        _em.BccRecipients.Add(_mail.Bcc[i].MailAddress.ToString());
                    }
                    else
                    {
                        _ea.Id = _mail.Bcc[i].ItemID;
                        _ea.Name = _mail.Bcc[i].ContactName;
                        _ea.Address = _mail.Bcc[i].MailAddress;

                        _em.BccRecipients.Add(_ea);
                    }
                }
            }

            _em.Subject = _mail.Subject;

            if (_mail.HTMLContent == "" || _mail.HTMLContent == null)
            {
                _em.Body = _mail.TextContent;
            }
            else
            {
                _em.Body = _mail.HTMLContent;
            }

            return _em;
        }

        public static void EmptyFolder(UserAccount _ua, string _targetFolderID)
        {
            ExchangeService _service = new ExchangeService();
            if (_service.RequestedServerVersion != ExchangeVersion.Exchange2007_SP1 && _service.RequestedServerVersion != ExchangeVersion.Exchange2010)
            {
                Folder _folder = Folder.Bind(ConnectionCache.Connections["EWS_" + _ua.MailAddress] as ExchangeService, _targetFolderID);

                _folder.Empty(DeleteMode.HardDelete, true);
            }
            else
            {
 
            }
        }
    }
}
